﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.Serialization;

using GameLibrary.Internal;
using GameLibrary.Internal.Converters;
using G.Model.Enums;

namespace G.Model
{
    [DataContract]
    public class GameElementDef : 
        INotifyPropertyChanged, System.IEquatable<GameElementDef>,
        HasValueDefs, HasName
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private GameSpaceDef _GameDef;
        
        [DataMember(Name="GameValueDefs")]
        private readonly GameValueDefs _GameValueDefs;

        [DataMember(Name="Location")]
        private GameLocation _Location;
        
        [DataMember(Name="Icon")]
        private string _IconString;
        
        [DataMember(Name="Player")]
        private string _PlayerString;
        
        [DataMember(Name="Name")]
        private string _Name;
        
        [DataMember(Name="Text")]
        private string _Text = "";
        
        [DataMember(Name="MoveStratagy")]
        private MoveStratagyEnum _MoveStratagy;
        
        [DataMember(Name="CollisionStratagy")]
        private CollisionStratagyEnum _CollisionStratagy;
        
        public GameElementDef(GameSpaceDef game, GameLocation point)
        {
            _GameDef = game;
            _Location = point;
            _Name = "Element-" + point.ToString();
            _PlayerString = "Player1";
            _IconString = "Man";
            _MoveStratagy = MoveStratagyEnum.NEIGHBORING;
            _CollisionStratagy = CollisionStratagyEnum.CONSUME;
            _GameValueDefs = new GameValueDefs(game);
        }
        
        [Browsable(false), IgnoreDataMemberAttribute]
        public GameSpaceDef GameDef
        {
            get { return _GameDef; }
            set 
            { 
                _GameDef = value; 
                _GameValueDefs.GameDef = value;
            }
        }

        public string Name
        {
            get { return _Name; }
        }
        
        public void SetName(string name) {
            _Name = name;
        }

        public GameValueDefs GameValueDefs
        {
            get { return _GameValueDefs; }
        }

        [TypeConverter(typeof(LocationConverter))]
        public GameLocation Location
        {
            get { return _Location; }
        }

        [TypeConverter(typeof(IconStringConverter))]
        public String Icon
        {
            get { return _IconString; }
            set { 
                _IconString = value;
                if (PropertyChanged != null) {
                    PropertyChanged(this, new PropertyChangedEventArgs(""));
                }
                if (_GameDef != null)
                {
                    _GameDef.GameElementDefs.FireElementPropertyChanged(this);
                }
                _GameDef.IsDirty = true;
            }
        }

        public String Text
        {
            get { return _Text; }
            set { 
                if (_Text != value)
                {
                    _Text = value;
                    if (PropertyChanged != null) 
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs(""));
                    }
                    if (_GameDef != null)
                    {
                        _GameDef.GameElementDefs.FireElementPropertyChanged(this);
                    }
                }
            }
        }
        
        [TypeConverter(typeof(PlayerStringConverter))]
        public String Player
        {
            get { return _PlayerString; }
            set
            {
                _PlayerString = value;
                if (_GameDef != null)
                {
                    _GameDef.GamePlayerDefs.DeterminePlayers(_GameDef);
                }
                if (_PlayerString == "Nothing")
                {
                    MoveStratagy = MoveStratagyEnum.NO_MOVE;
                }
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(""));
                }
                if (_GameDef != null)
                {
                    _GameDef.GameElementDefs.FireElementPropertyChanged(this);
                }
            }
        }

        public CollisionStratagyEnum CollisionStratagy
        {
            get { return _CollisionStratagy; }
            set
            {
                _CollisionStratagy = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(""));
                }
                if (_GameDef != null)
                {
                    _GameDef.GameElementDefs.FireElementPropertyChanged(this);
                }
            }
        }
        
        public MoveStratagyEnum MoveStratagy
        {
            get { return _MoveStratagy; }
            set
            {
                _MoveStratagy = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(""));
                }
                if (_GameDef != null)
                {
                    _GameDef.GameElementDefs.FireElementPropertyChanged(this);
                }
            }
        }

        [TypeConverter(typeof(ReadOnlyCollectionConverter)), IgnoreDataMember ]
        public ICollection<GameLocation> MovePoints
        {
            get
            {
                MovePointGenerator g = new MovePointGenerator();
                g.Start = Location;
                g.Moves = MoveStratagy;
                return g.Generate();
            }
        }

        public bool Equals(GameElementDef other)
        {
            return (other.Location.X == _Location.X && 
                other.Location.Y == _Location.Y); 
        }

        public override string ToString()
        {
            return "{ " + this.Location + ", " + this.Player + " }";
        }

    }
}
